package com.hg.miaosha.order;

import com.hg.miaosha.R;
import com.hg.miaosha.product.ProductDO;
import com.hg.miaosha.product.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: skh
 * @Date: 2019/10/16 15:40
 * @Description:
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductService productService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static ConcurrentHashMap<Integer, Boolean> productSoldOutMap = new ConcurrentHashMap<>();

    //把库存放到redis,吞吐量:1139
    @PostConstruct
    public void initStock() {
        List<ProductDO> productList = productService.getProductList();
        for (ProductDO productDO : productList) {
            stringRedisTemplate.opsForValue().set("seckill:productId:" + productDO.getId(), productDO.getStock() + "");
        }
    }

    //测试库存:300
    @GetMapping("/seckill/{productId}")
    public R seckill(@PathVariable Integer productId) {
        try {
            //引入JVM缓存:1600
            if (productSoldOutMap.get(productId) != null) {
                return R.error("库存不足,秒杀失败");
            }

            Long decrement = stringRedisTemplate.opsForValue().decrement("seckill:productId:" + productId);
            //注意:这里是<0
            if (decrement < 0) {
                productSoldOutMap.put(productId, true);

                //注意:这里也要加回库存,为了让库存始终保持为0
                stringRedisTemplate.opsForValue().increment("seckill:productId:" + productId);
                return R.error("库存不足,秒杀失败");
            }

            orderService.seckill(productId, 1);
        } catch (Exception e) {
            productSoldOutMap.remove(productId);
            //如果下单时抛出异常,就在redis加回库存,不然会数据不一致.
            stringRedisTemplate.opsForValue().increment("seckill:productId:" + productId);
            return R.error(e.getMessage());
        }
        return R.success(null);
    }
}
